/*
 * Intermote.h -- common Intermote definitions
 *
 * Copyright (C) Andrey Vihrov <andrey.vihrov@gmail.com>, 2010
 * Copyright (C) Askar Salimbaev <ghostinshell@gmail.com>, 2010
 *
 * This file is part of Intermote.
 *
 * Intermote is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Intermote is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Intermote.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef INTERMOTE_H

	#define INTERMOTE_H

	#include <AM.h>
	#include <TinyError.h>

	/**
	 * Intermote radio packet AM types
	 */
	enum {

		/**
		 * Routing component traffic
		 */
		AM_ROUTING  = 100,

		/**
		 * Flooding component traffic
		 */
		AM_FLOODING = 101,

	};


	/**
	 * Routed data identifier type
	 */
	typedef uint8_t im_rt_id_t;

	/**
	 * Routed data packet types
	 */
	enum {
		/**
		 * Various requests and replies
		 */
		RT_FIRSTBLOCK         = 1,
		RT_FIRSTBLOCK_REPLY   = 2,
		RT_READ               = 3,
		RT_READ_REPLY         = 4,
		RT_WRITE              = 5,
		RT_WRITE_REPLY        = 6,
		RT_PROPERTY_SET       = 7,
		RT_PROPERTY_GET       = 8,
		RT_ALLOCATE           = 9,
		RT_ALLOCATE_REPLY     = 10,
		RT_ERASEBLOCK         = 11,
		RT_DROP               = 12,
		RT_PROPERTY_SET_REPLY = 13,
		RT_PROPERTY_GET_REPLY = 14,

	};

	/**
	 * Stream offset type
	 */
	typedef uint32_t im_off_t;


	/**
	 * Flooding data identifier type
	 */
	typedef uint8_t im_flood_id_t;
	// TODO: Define flood packet types
	enum {
		FL_ALLOCATE = 0,

		FL_RESERVE  = 1,
	};

	/**
	 * Maximum number of hops in packet flooding
	 */
	#define FL_MAX_HOPS      6


	/**
	 * Data block id type
	 */
	typedef uint32_t im_block_id_t;
	#define IM_NOBLOCK       0xFFFFFFFF


	/**
	 * Block properties are 32-bit pieces of data
	 */
	enum im_block_property {
		IM_PROP_NEXT_ID,
		IM_PROP_REPLICATED_ID,
		IM_PROP_REPLICATION_LEVEL,
		IM_PROP_REPLICATION_ID_1,
		IM_PROP_REPLICATION_ID_2,
		IM_PROP_REPLICATION_ID_3,

		IM_PROP_COUNT
	};

	/**
	 * Data chunk size - must fit in a network packet
	 */
	//TODO Change this to something real
	#define IM_CHUNK_SIZE    16

	/**
	 * Data block size (without metadata)
	 */
	//TODO Change this to something real?
	#define IM_BLOCK_SIZE_LOG2 16
	#define IM_BLOCK_SIZE_REAL ((im_off_t)64 * 1024 - 4 * IM_PROP_COUNT - 1)
	#define IM_BLOCK_SIZE    (IM_BLOCK_SIZE_REAL - IM_BLOCK_SIZE_REAL % IM_CHUNK_SIZE)

	/**
	 * Data chunk type
	 */
	struct im_chunk {
		uint8_t data[IM_CHUNK_SIZE];
	};


	/**
	 * Queue size in IMLocalToNetwork
	 */
	#define IM_INCOMING_QUEUE_SIZE    5

	/**
	 * Request queue in IMLocalToNetwork
	 */
	// TODO: Consider allocating chunk buffer in heap and only when needed
	typedef struct {
		uint8_t req;
		am_addr_t source;
		uint32_t block;
		uint32_t offset;
		struct im_chunk chunk;
	} queued_request_t;

	/**
	 * Storage queue size
	 */
	#define IM_STORAGE_QUEUE_SIZE    5

	/**
	 * Storage request queue
	 */
	typedef struct {
		uint8_t req;
		uint8_t id;
		uint8_t prop;
		uint32_t block;
		uint32_t offset;
		struct im_chunk* userbuf;
	} storage_request_t;

	/**
	 * Requests and replies
	 */
	typedef nx_struct {
		nx_uint32_t block;
		nx_uint32_t offset;
	} read_request_t;

	typedef nx_struct {
		nx_uint8_t data[IM_CHUNK_SIZE];
	} read_reply_t;

	typedef nx_struct {
		nx_uint8_t status; //error_t
		nx_uint32_t block;
	} allocate_reply_t;

	typedef nx_struct {
		nx_uint32_t block;
		nx_uint32_t offset;
		nx_uint8_t data[IM_CHUNK_SIZE];
	} write_request_t;

	typedef nx_struct {
		nx_uint32_t block;
	} erase_request_t;

	typedef nx_struct {
		nx_uint8_t count;
	} reserve_request_t;

	typedef nx_struct {
		nx_uint8_t property;
		nx_uint32_t block;
	} get_property_request_t;

	typedef nx_struct {
		nx_uint32_t data;
	} get_property_reply_t;

	typedef nx_struct {
		nx_uint8_t property;
		nx_uint32_t block;
		nx_uint32_t data;
	} set_property_request_t;


	/**
	 * Additional error_t value
	 */
	#define EEOF             (ELAST + 1)


	/**
	 * Network operation timeout value, ms
	 */
	#define IM_TIMEOUT       5000


	#define UQ_IM_TIMEOUT    "IMTimeoutP"
	#define UQ_IM_COREINIT   "IntermoteM.SplitControl"

#endif /* INTERMOTE_H */
